import random
import re
import time
import argparse
from typing import List, Optional

from config import CONFERENCES
from dblp_crawler import DBLPCrawler
from models import Conference
from researchr_crawler import ResearchrCrawler
from utils import logger, save_papers_to_excel


def determine_type(url):
    # 为每种类型的URL模式定义一个列表，这样可以有多个模式对应同一个type
    patterns = {
        'researchr': [
            r'^https://conf\.researchr\.org/',
            r'^https://2024\.esec-fse\.org/'
        ],
        'dblp': [
            r'^https://dblp\.org/'
        ]
    }

    for type_name, pattern_list in patterns.items():
        for pattern in pattern_list:
            if re.match(pattern, url):
                return type_name

    return None


def create_conference_objects(
        selected_conferences: Optional[List[str]] = None,
        selected_years: Optional[List[int]] = None,
        selected_tracks: Optional[List[str]] = None
) -> List[Conference]:
    """创建会议对象列表，支持筛选"""
    conferences = []

    for conf_name, conf_items in CONFERENCES.items():
        # 筛选会议名称
        if selected_conferences and conf_name not in selected_conferences:
            continue

        for conf_item in conf_items:
            # 筛选年份
            if selected_years and conf_item['year'] not in selected_years:
                continue

            # 筛选track
            if selected_tracks and conf_item['track'] not in selected_tracks:
                continue

            conference = Conference(
                name=conf_name,
                year=conf_item['year'],
                url=conf_item['url'],
                track=conf_item['track'],
                type=determine_type(conf_item['url'])
            )
            conferences.append(conference)

    return conferences


def parse_arguments():
    """解析命令行参数"""
    parser = argparse.ArgumentParser(description='抓取会议论文信息')
    parser.add_argument('--conference', '-c', nargs='+',
                        help='指定会议名称，如 ASE FSE ICSE ISSTA（不指定则抓取全部）')
    parser.add_argument('--year', '-y', type=int, nargs='+',
                        help='指定年份，如 2023 2024（不指定则抓取全部）')
    parser.add_argument('--track', '-t', nargs='+',
                        help='指定track，如 research industry seis seip（不指定则抓取全部）')

    return parser.parse_args()


def main():
    """主函数"""
    # 解析命令行参数
    args = parse_arguments()

    # 打印筛选条件
    logger.info(
        f"筛选条件 - 会议: {args.conference or '全部'}, 年份: {args.year or '全部'}, Track: {args.track or '全部'}")

    papers_data = []
    conferences = create_conference_objects(
        selected_conferences=args.conference,
        selected_years=args.year,
        selected_tracks=args.track
    )

    if not conferences:
        logger.warning("没有找到匹配的会议配置")
        return

    logger.info(f"找到 {len(conferences)} 个匹配的会议配置")

    dblp_crawler = DBLPCrawler()
    researchr_crawler = ResearchrCrawler()

    # 处理每个会议
    for conference in conferences:
        logger.info(f"{'=' * 50}")
        logger.info(f"正在处理 {conference.name} {conference.year} {conference.track} {conference.url}")
        logger.info(f"{'=' * 50}")
        if conference.type == 'dblp':
            papers = dblp_crawler.crawl_conference(conference)
            papers_data.extend(papers)
        elif conference.type == 'researchr':
            papers = researchr_crawler.crawl_conference(conference)
            papers_data.extend(papers)
        # 避免请求过于频繁
        time.sleep(random.uniform(2, 4))

    # 保存结果
    timestamp = int(time.time())
    filename = f"Conference_Papers_{timestamp}.xlsx"
    save_papers_to_excel(papers_data, filename)

    # 打印统计信息
    total_papers = len(papers_data)
    logger.info(f"总共收集了 {total_papers} 篇论文")
    logger.info(f"结果已保存到: {filename}")

    # 按会议统计
    conference_stats = {}
    for paper in papers_data:
        key = f"{paper.conference}_{paper.year}_{paper.track}"
        if key not in conference_stats:
            conference_stats[key] = 0
        conference_stats[key] += 1

    for conf_key, count in conference_stats.items():
        logger.info(f"{conf_key}: {count} 篇论文")


if __name__ == '__main__':
    main()